package com.kk.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kk.common.ResultCode;
import com.kk.constrants.RedisConstants;
import com.kk.exceptions.BusinessException;
import com.kk.mapper.SysMenuMapper;
import com.kk.mapper.SysRoleMenuMapper;
import com.kk.pojo.entity.SysMenu;
import com.kk.pojo.entity.SysRoleMenu;
import com.kk.pojo.entity.SysUserRole;
import com.kk.pojo.vo.MenuTreeVO;
import com.kk.pojo.vo.UserListVO;
import com.kk.pojo.vo.UserPermissionVO;
import com.kk.service.SysMenuService;
import com.kk.service.SysRoleMenuService;
import com.kk.service.SysUserRoleService;
import com.kk.utils.RedisUtils;
import com.kk.utils.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author kl
 * @version 1.0
 * @description: TODO
 * @date 2025/10/13 下午5:51
 */
@Service
@RequiredArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    private final SysUserRoleService sysUserRoleService;
    private final RedisUtils redisUtils;




    @Override
    public List<SysMenu> getMenusByRoleIds(List<BigInteger> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return Collections.emptyList();
        }
        // ✅ 使用连表查询，一次性获取所有菜单
        return this.baseMapper.selectMenusByRoleIds(roleIds);
    }

    @Override
    public List<MenuTreeVO> getMenuTreeByUserId(BigInteger userId) {
        // 1. 查询用户角色ID
        List<SysUserRole> sysUserRoles = sysUserRoleService.selectRoleByUserId(userId);
        if (CollectionUtils.isEmpty(sysUserRoles)) {
            return Collections.emptyList();
        }

        List<BigInteger> roleIds = sysUserRoles.stream()
                .map(SysUserRole::getRoleId)
                .collect(Collectors.toList());

        // 2. 通过连表查询获取菜单（已经在 SQL 中做了排序）
        List<SysMenu> menus = getMenusByRoleIds(roleIds);

        // 3. 构建树形结构
        return buildMenuTree(menus);
    }

    @Override
    public List<MenuTreeVO> buildMenuTree(List<SysMenu> menus) {
        if (CollectionUtils.isEmpty(menus)) {
            return Collections.emptyList();
        }

        // 转换为VO（SQL已排序，无需再次排序）
        List<MenuTreeVO> menuVOList = menus.stream()
                .map(this::convertToVO)
                .toList();

        // 构建 Map 便于查找父节点
        Map<BigInteger, MenuTreeVO> menuMap = menuVOList.stream()
                .collect(Collectors.toMap(MenuTreeVO::getId, menu -> menu));

        // 找出根节点并构建树
        List<MenuTreeVO> rootMenus = new ArrayList<>();
        for (MenuTreeVO menu : menuVOList) {
            BigInteger parentId = menu.getParentId();
            if (parentId == null || parentId.equals(BigInteger.ZERO)) {
                rootMenus.add(menu);
            } else {
                MenuTreeVO parent = menuMap.get(parentId);
                if (parent != null) {
                    parent.getChildren().add(menu);
                }
            }
        }

        return rootMenus;
    }

    @Override
    public Set<String> getPermissionsByUserId(BigInteger userId) {
        // 1. 查询用户角色ID
        List<SysUserRole> userRoles = sysUserRoleService.selectRoleByUserId(userId);
        if (CollectionUtils.isEmpty(userRoles)) {
            return Collections.emptySet();
        }

        List<BigInteger> roleIds = userRoles.stream()
                .map(SysUserRole::getRoleId)
                .collect(Collectors.toList());

        // 2. 通过连表查询获取菜单
        List<SysMenu> menus = getMenusByRoleIds(roleIds);

        // 3. 提取权限标识
        return menus.stream()
                .filter(menu -> menu.getPermission() != null && !menu.getPermission().isEmpty())
                .map(SysMenu::getPermission)
                .collect(Collectors.toSet());
    }

    @Override

    public List<MenuTreeVO> getMenusByUserIdService() {
        // 首先拿到用户id
        BigInteger userId = SecurityUtils.getCurrentUserId();
        if (Objects.isNull(userId)) {
            log.error("拿不到用户id，请求不合法");
            throw new BusinessException(ResultCode.FAILED.getCode(),"用户id为空");
        }
        // 根据用户id去redis里面拿
        String redisKey = RedisConstants.USER_PREFIX + userId;
        UserPermissionVO cache = redisUtils.get(redisKey);
        // 如果为空那么得去查找数据库
        if (ObjectUtils.isEmpty(cache) || ObjectUtils.isEmpty(cache.getMenus())) {
            List<MenuTreeVO> menuTreeByUserId = getMenuTreeByUserId(userId);
            // 加入缓存
            redisUtils.set(redisKey, menuTreeByUserId);
            // 返回
            return menuTreeByUserId;
        }
        return cache.getMenus();
    }

    @Override
    public List<MenuTreeVO> getAllMenus() {
        // 这个查询的少，那么就直接去数据库里面拿，不需要缓存
        List<SysMenu> list = this.list();
        // 进行转换
        return list.stream()
                .map(this::convertToVO)
                .toList();
    }


    private MenuTreeVO convertToVO(SysMenu menu) {
        MenuTreeVO vo = new MenuTreeVO();
        BeanUtils.copyProperties(menu, vo);
        return vo;
    }
}
